#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <memory>
#include <functional>
#include "common.hpp"
#include "Connection.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"

using namespace LogMoudle;

#define SIZE 1024
class Channel : public Connection
{
public:
    Channel(int sockfd, const InetAddr client)
        : _sockfd(sockfd), _client(client)
    {
        SetNoBlock(_sockfd); // 初始化时把文件描述符设置为非阻塞模式
    }
    void Recver() override
    {
        char buffer[SIZE];
        while (true)
        {
            buffer[0] = 0;
            int n = recv(_sockfd, buffer, sizeof(buffer)-1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer;
            }
            else if (n == 0)
            {
                Excepter();
                return;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Excepter();
                    break;
                }
            }
        }
        LOG(loglevel::DEBUG) << "Channel: Inbuffer:\n"<< _inbuffer;
        if(!_inbuffer.empty())
        {
            _outbuffer+=_handler(_inbuffer);
        }
        if(!_outbuffer.empty())
        {
            Sender();
        }
    }
     void Sender() override
    {
        while (true)
        {
            int n = send(_sockfd, _outbuffer.c_str(), sizeof(_outbuffer.c_str()), 0);
            if (n > 0)
            {
                _outbuffer.erase(0,n);
                if(_outbuffer.empty())
                {
                    break;
                }
            }
            else if (n == 0)
            {
                break;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Excepter();
                    break;
                }
            }
        }
        //当发送缓冲区满的时候但_outbuffer还有数据时，将多余数据设置EPOLL中，当发送缓冲区有空间时，OS自动把epoll里的写事件拷贝到缓冲区中
        if(!_outbuffer.empty())
        {
            GetOwner()->EnableReadWrite(_sockfd,true,true);
        }
        else{
            GetOwner()->EnableReadWrite(_sockfd,true,false);
        }

    }
    void Excepter() override
    {
        GetOwner()->DelConnection(_sockfd);
    }
    int GetFd() override
    {
        return _sockfd;
    }
    std::string &Inbuffer()
    {
        return _inbuffer;
    }
    void AppendOutBuffer(const std::string &out)
    {
        _outbuffer += out;
    }
    ~Channel()
    {
    }

private:
    int _sockfd;
    std::string _inbuffer;
    std::string _outbuffer;
    InetAddr _client;
};